package com.scs.application.core.configuration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.scs.application.core.mvc.converter.StringToDateConverter;
import com.scs.application.core.mvc.converter.StringTrimConverter;
import com.scs.application.core.mvc.mapping.ApiVersioningRequestMappingHandlerMapping;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * web mvc config, 当在oauth项目中，不启用，否则会造成token序列化错误
 *
 */
@SuppressWarnings("SpringJavaConstructorAutowiringInspection")
@Slf4j
@AllArgsConstructor
@Configuration
@ConditionalOnMissingClass("fortec.common.oauth.endpoints.LogoutTokenEndpoint")
@ConditionalOnExpression("${project.webmvc.default-config.enabled:true}")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
//public class WebMvcConfig extends WebMvcConfigurationSupport  {
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    private final ResourceProperties resourceProperties;

    private final ObjectMapper objectMapper;

    @Value("${res.real-path}")
    private String resRealPath;

    /**
     * 这个地方要重新注入一下资源文件，不然不会注入资源的，也没有注入requestHandlerMappping,相当于xml配置的
     * <p>
     * <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>
     * <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/>
     * </p>
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/swagger-ui.html**")
                .addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");


        // 资源路径映射，用于存放运行时上传的文件
        registry.addResourceHandler("/res/**")
                .addResourceLocations("file:" + resRealPath);

        // 配置静态资源
        String[] staticLocations = resourceProperties.getStaticLocations();
        registry.addResourceHandler("/**")
                .addResourceLocations((staticLocations))
                .setCacheControl(CacheControl.noCache());

    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedMethods("OPTIONS", "GET", "POST", "PUT", "DELETE").allowedHeaders("*");
    }

    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.extendMessageConverters(converters);

        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = null;

        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
                converters.remove(converter);
                break;
            }
        }
        if (mappingJackson2HttpMessageConverter == null) {
            mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        }

        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);

        /**
         * {@link org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters }
         * 当通过网页直接访问  text/html 时，{@link org.springframework.web.bind.annotation.ResponseBody} 默认返回的为xml类型，添加 converter 所支持的 mediaType
          */
        List<MediaType> tmpSupportedMediaTypes = mappingJackson2HttpMessageConverter.getSupportedMediaTypes();
        ArrayList<MediaType> supportedMediaTypes = Lists.newArrayList(tmpSupportedMediaTypes);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);

        converters.add(0, mappingJackson2HttpMessageConverter);

        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        converters.add(0, stringHttpMessageConverter);
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringTrimConverter());
        registry.addConverter(new StringToDateConverter());
    }


    @Autowired
    private Environment env;

    @Override
    protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {

        Boolean enabled = env.getProperty("project.webmvc.version-control.enabled", Boolean.class);
        if (enabled == null || !enabled) {
            return super.createRequestMappingHandlerMapping();
        }
        log.info("Api version control is enabled.");
        return new ApiVersioningRequestMappingHandlerMapping();
    }
}
